import 'dart:math';

import 'package:flutter/material.dart';

typedef ProgressChanged<double> = void Function(double value);

num degToRad(num deg) => deg * (pi / 180.0);
num radToDeg(num rad) => rad * (180.0 / pi);

class CircleProgressWidget extends StatelessWidget {
  final double radius;
  final double progress;
  final double dotRadius;
  final double shadowWidth;
  final Color shadowColor;
  final Color ringColor;
  final Color startColor;
  final Color endColor;

  const CircleProgressWidget({
    Key key,
    @required this.radius,
    @required this.dotRadius,
    this.shadowWidth = 2.0,
    this.shadowColor = Colors.black12,
    this.ringColor =  Colors.blue, //圆环的颜色
    this.progress,
    this.startColor = Colors.white,
    this.endColor = Colors.blue,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final double width = radius * 2.0;
    final size = new Size(width, width);
    return  Container(
      alignment: FractionalOffset.center,
      child: CustomPaint(
        size: size,
        painter: ProgressPainter(
            dotRadius: dotRadius,
            shadowWidth: shadowWidth,
            shadowColor: shadowColor,
            ringColor: ringColor,
            progress: progress,
            startColor: startColor,
            endColor: endColor
        ),
      ),
    );
  }
}

class ProgressPainter extends CustomPainter {
  final double dotRadius;
  final double shadowWidth;
  final Color shadowColor;
  final Color dotColor;
  final Color ringColor;
  final double progress;
  final Color startColor;
  final Color endColor;

  ProgressPainter({
    this.dotRadius,
    this.shadowWidth = 2.0,
    this.shadowColor = Colors.black12,
    this.ringColor = Colors.blue,
    this.dotColor,
    this.progress,
    this.startColor,
    this.endColor,
  });

  @override
  void paint(Canvas canvas, Size size) {

    final double center = size.width * 0.5;
    final Offset offsetCenter = Offset(center, center);
    final double drawRadius = size.width * 0.5 - dotRadius/2;
    final angle = 360.0 * progress;
    final double radians = degToRad(angle);
    final double outerRadius = center + dotRadius;
    // draw ring.
    final ringPaint = Paint()
      ..style = PaintingStyle.stroke
      ..color = ringColor
      ..strokeWidth = (dotRadius*2);
    canvas.drawCircle(offsetCenter, drawRadius, ringPaint);

    // draw progress.
    if (progress > 0.0) {
      final progressWidth = dotRadius*2;
      final double offset = asin(progressWidth * 0.5 / drawRadius);
      if (radians > offset) {
        canvas.save();
        canvas.translate(0.0, size.width);
        canvas.rotate(degToRad(-90.0));
        final Gradient gradient = new SweepGradient(
          endAngle: radians,
          colors: [
            startColor,
            endColor
          ],
        );
        final Rect arcRect =
        Rect.fromCircle(center: offsetCenter, radius: drawRadius);
        final progressPaint = Paint()
          ..style = PaintingStyle.stroke
          ..strokeCap = StrokeCap.round
          ..strokeWidth = progressWidth
          ..shader = gradient.createShader(arcRect);
        canvas.drawArc(
            arcRect, offset, radians - offset, false, progressPaint);
        canvas.restore();
      }
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
